#include "image_manager.h"
#include <fstream>
#include <cassert>

#define HELP "uso: " << argv[0] <<\
			" [-i <input_file>=rayitos.(in|png)] "\
			"-o [<output_file>=rayitos.(out|png)]"\
			"[-v] (-i2m | -m2i) -s seed -m cantRayos -g sigma" << endl

char locate_option(char** options, char options_size, char* str);

using namespace std;
int verbose = 0;

enum ConvertionMode {
    IMAGE_2_MATRIX = 0,
    MATRIX_2_IMAGE = 1,
    UNDEFINED_CM   = 2
};

enum OptionType {
	  INPUT_FILE       = 0,
      OUTPUT_FILE      = 1,
	  VERBOSE          = 2,
	  IMAGE_2_MATRIX_O = 3,
  	  MATRIX_2_IMAGE_O = 4,
  	  SEED = 5,
  	  CANT_RAYOS = 6,
  	  SIGMA = 7,
	  OPTION_NOT_RECOGNIZED
}; 

int main(int argc, char* argv[]) {
	char* input_file = NULL;
	char* output_file = NULL;
 	char* options[] = {"-i", "-o", "-v", "-i2m", "-m2i", "-s", "-m", "-g"}; 
	char options_size = 8;
	ConvertionMode c_mode = UNDEFINED_CM;
	unsigned seed, cant_rayos;
	double sigma;
	char seed_passed= 0, sigma_passed= 0, cant_rayos_passed= 0;

	for(int i = 1; i < argc; i++) {
		char option = locate_option(options, options_size, argv[i]);
		
        switch (option) {
    		case INPUT_FILE:
    			input_file = argv[i+1];
    			break;
    		case OUTPUT_FILE:
    			output_file = argv[i+1];
    			break;
    		case VERBOSE:
    			verbose = 1;
    			break;
				case IMAGE_2_MATRIX_O:
					c_mode = IMAGE_2_MATRIX;
					break;
				case MATRIX_2_IMAGE_O:
					c_mode = MATRIX_2_IMAGE;
					break;
				case SEED:
					seed= atoi(argv[i+1]);
					seed_passed= 1;
					break;
				case CANT_RAYOS:
					cant_rayos= atoi(argv[i+1]);
					cant_rayos_passed= 1;
					break;
				case SIGMA:
					sigma= atof(argv[i+1]);
					sigma_passed= 1;
					break;
				}
	} 

	if ( c_mode == UNDEFINED_CM ) { 
        cerr << "ERROR: no hay modo de ejecucion" << endl ;
        cerr << HELP;
        return 1;
    }
        
	
	if(input_file == NULL) {
        if ( c_mode == IMAGE_2_MATRIX )
    	   input_file = "rayitos.png";
    	else if ( c_mode == MATRIX_2_IMAGE)
    	   input_file = "rayitos.in";   
    }
		
	if(output_file == NULL ) {
        if ( c_mode == IMAGE_2_MATRIX )
    	   output_file = "rayitos.out";
    	else if ( c_mode == MATRIX_2_IMAGE)
    	   output_file = "rayitos.png";
    }
    
	if(verbose) {
		cout << "Parametros:" << endl;
		cout << "\tinput_file:" << input_file << endl;
		cout << "\toutput_file:" << output_file << endl;
		cout << "\tc_mode: ";
		switch(c_mode) {
		case MATRIX_2_IMAGE:
			cout << "MATRIX2IMAGE";
			break;
		case IMAGE_2_MATRIX:
			cout << "IMAGE_2_MATRIX";
			break;
		default:
			cout << "indefinido";
			if(seed_passed) cout << "seed: " << seed << endl;
			if(cant_rayos_passed) cout << "cant_rayos: " << cant_rayos << endl;
			if(sigma_passed) cout << "sigma: " << cant_rayos << endl;
		}
		cout << endl;
		cout << endl;
			
	}
	ifstream in(input_file);

	if ( !in.good() ) {
		cerr << "No se puede abrir el archivo " << input_file << endl;
		cerr << HELP;
		return 1;
	}

    ImageManager ib;  
    Matrix m; 

    if ( c_mode == MATRIX_2_IMAGE ) {
       	ifstream s_matrix(input_file);
     		s_matrix >> m; 

				for(int i= 0; i < m.rows(); i++) {
					for(int j= 0; j<m.cols(); j++) {
						m(i,j)--;
					}
				}

     		s_matrix.close(); 
				if(verbose) {
					cout << "matriz: " << endl;
					cout << m;
					cout << endl;
				}
           
        ib.saveMatrix(m, output_file);  
  
    	return 0;
    } else if ( c_mode == IMAGE_2_MATRIX ) {
				if(!(seed_passed && cant_rayos_passed && sigma_passed)) {
					cerr << "los parametros -s, -m y -g son obligatorios en el modo -i2m" << endl;
					cerr << HELP;
				}
        ib.loadMatrix(input_file, m);
				ofstream o(output_file);        
				for(int i= 0; i < m.rows(); i++) {
					for(int j= 0; j<m.cols(); j++) {
						m(i,j)++;
					}
				}
				o << m.cols() << " " << 
					cant_rayos << " " << 
					seed << " " << 
					sigma << endl;
				o << m;
				o.close();

				return 0;
		}


}


char locate_option(char** options, char options_size, char* str) {
	for(int i = 0; i < options_size; i++) {
		if ( strcmp(options[i], str) == 0 )
			return i;
	}

	return options_size + 1;
}
